﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using System.IO;
using System.Diagnostics;

namespace UIControls
{
    /// <summary>
    /// Will display the outputs of a PS rendering for a particular PS file.
    /// </summary>
    public partial class PSPane : UserControl
    {
        public PSPane()
        {
            InitializeComponent();
            renderedImages.SizeChanged += new EventHandler(renderedImages_SizeChanged);
        }

        WaitForRender waitPane = null;
        bool imageLoaded = false;

        /// <summary>
        /// Put up the "rendering" pane. Make sure to lock so we don't get on each others feet!
        /// </summary>
        /// <param name="e"></param>
        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);

            ///
            /// Lock so that we know what is going on here!
            /// 

            lock (this)
            {
                if (!imageLoaded)
                {
                    renderedImages.Visible = false;
                    waitPane = new WaitForRender();
                    Height = waitPane.Height;
                    Controls.Add(waitPane);
                    waitPane.Dock = DockStyle.Fill;
                    waitPane.Visible = true;
                    waitPane.BringToFront();
                }
            }
        }

        /// <summary>
        /// Our sub-dude change size. We need to match it exactly.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void renderedImages_SizeChanged(object sender, EventArgs e)
        {
            Width = renderedImages.Width;
            Height = renderedImages.Height;
        }

        private FileInfo _psFile = null;

        /// <summary>
        /// Where the jpeg's are located.
        /// </summary>
        private DirectoryInfo TempFilesLocation = null;

        /// <summary>
        /// Get/Set the file that will be rendered. Can only be set once.
        /// </summary>
        public FileInfo PSFile
        {
            get { return _psFile; }
            set
            {
                lock (this)
                {
                    if (_psFile != null)
                    {
                        throw new ArgumentException("PSFile can be set only once!");
                    }
                    _psFile = value;
                    if (_psFile != null && _psFile.Exists)
                    {
                        ThreadPool.QueueUserWorkItem((o) => Render());
                    }
                }
            }
        }

        private List<FileStream> imageStreams = new List<FileStream>();

        /// <summary>
        /// Run the render. We expect this to be running in
        /// a non-UI thread.
        /// </summary>
        /// <returns></returns>
        private void Render()
        {
            using (var itr = new Utilities.GSJpeggerAutoRotate(PSFile))
            {
                var files = from f in itr
                            select f;
                foreach (var f in files)
                {
                    FileStream fs = new FileStream(f.FullName, FileMode.Open, FileAccess.Read);
                    imageStreams.Add(fs);
                    Image img = Image.FromStream(fs);

                    PrepForFirstImage();

                    renderedImages.Add(img);
                }

                TempFilesLocation = itr.TempFileLocation;
            }
        }

        /// <summary>
        /// Make sure the wait-for-loading thing is done away with
        /// </summary>
        private void PrepForFirstImage()
        {
            if (InvokeRequired)
            {
                Invoke ((MethodInvoker) (() => PrepForFirstImage()));
            }
            else
            {
                if (!imageLoaded)
                {
                    lock (this)
                    {
                        if (waitPane != null)
                        {
                            Controls.Remove(waitPane);
                            waitPane = null;
                        }
                        imageLoaded = true;
                        renderedImages.Visible = true;
                    }
                }
            }
        }



        protected override void OnHandleDestroyed(EventArgs e)
        {
            base.OnHandleDestroyed(e);

            foreach (var fs in imageStreams)
            {
                fs.Close();
            }

            TempFilesLocation.Refresh();
            if (TempFilesLocation != null && TempFilesLocation.Exists)
            {
                try
                {
                    TempFilesLocation.Delete(true);
                }
                catch
                {
                }
            }
        }
    }
}
